﻿using StackExchange.Redis.Extensions.Core.Abstractions;
using System;
using System.Threading;
using System.Threading.Tasks;

namespace Solution.Core.Repository
{
    public class RedisClient : IRedisSingletoneClient
    {
        private readonly IRedisClient _redisClient;

        public RedisClient(IRedisClient redisClient)
        {
            _redisClient = redisClient;
        }

        public async Task<bool> AddAsync<T>(string key, T value, int db = 0)
        {
            return await _redisClient.GetDb(db).AddAsync(key, value);
        }

        public async Task<bool> SetAddAsync<T>(string key, T value, int db = 0) where T : class
        {
            return await _redisClient.GetDb(db).SetAddAsync(key, value);
        }

        public async Task<bool> ExistsAsync(string key, int db = 0)
        {
            return await _redisClient.GetDb(0).ExistsAsync(key);
        }

        public async Task<T> GetAsync<T>(string key, int db = 0)
        {
            return await _redisClient.GetDb(0).GetAsync<T>(key);
        }

        public async Task<bool> Lock(string key, int expireTimeSeconds = 10, int waitTimeSeconds = 3)
        {
            bool locked;
            while (!(locked = await _redisClient.Db0.Database.LockTakeAsync($"lock_{key}", "", TimeSpan.FromSeconds(expireTimeSeconds))) && waitTimeSeconds > 0)
            {
                waitTimeSeconds -= 1;
                Thread.Sleep(1000);
            }

            return locked;
        }

        public async Task<bool> UnLock(string key)
        {
            return await _redisClient.Db0.Database.LockReleaseAsync($"lock_{key}", "");
        }
    }
}